#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN MVC MODULE FOR THN WEB SERVER

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For use in commercial software, please obtain a commercial license from THN Solutions LLC.    

  + For use in free software, this library is licensed under GPL version 3. A summary of 
	GPLv3 is listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt 
	included with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 14-Apr-13 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

using Thn;
using Thn.IO;
using Thn.Web;
using Thn.Web.Mvc;
using Thn.Web.Razor;
#endregion

namespace Demo
{
    /// <summary>
    /// 
    /// </summary>
#if DEBUG 
    public
#else
    public
#endif 
    partial class fmMain : Form
    {
        #region Fields
        WebServer mServer;
        string mRootPath;

        //
        MvcModule mMvcModule;
        #endregion

        #region Properties
        #endregion

        #region UI Events processing

        #region btnGenerateCode_Click
        private void btnGenerateCode_Click(object sender, EventArgs e)
        {
            /*
             * The RAZOR basically works as followed:
             * + From a text template, generate codes
             * + From codes, generate executable assembly
             * + Invoke that assembly.
             * 
             * In this example, we'll see how the first step (text -> codes) is done.
             * 
             */

            string input = @"Hello there, the time now is @DateTime.Now";
            var engine = new RazorEngine<ViewTemplate>();
            RazorCompileArgs args = new RazorCompileArgs();
            args.CompileToMemory = true;//we don't need to save compiled assembly to disk in this example
            args.GenerateCodeAsText = true;//we do need to see the result code
            args.GeneratedNamespace = "MyNamespace";
            args.GeneratedClassName = "MyClass";

            using (TextReader reader = new StringReader(input))
            {
                var result = engine.ParseAndCompileTemplate(reader, args);

                //display result
                if (result.IsSuccessful) txtResult.Text = result.GeneratedCodes;
                else
                {
                    string txt = "ERROR:\r\n" + result.ErrorMessage;
                    txt += "\r\n\r\nGENERATED CODE:\r\n";
                    txt += result.GeneratedCodes;
                    txtResult.Text = txt;
                }
            }
        }
        #endregion

        #region btnManualRender_Click
        private void btnManualRender_Click(object sender, EventArgs e)
        {
            /*
             * In this example, we'll use a view renderer to execute
             * a view template with the view is generated from a .cshtml file
             * on disk.
             */

            //the renderer responsible for rendering view
            RazorViewRenderer renderer = new RazorViewRenderer();

            //the path translator is responsible for resolving the actual location
            //on disk of the view files
            UriToLocalPathTranslator translator = new UriToLocalPathTranslator();
            translator.Root = "Views";
            renderer.PathTranslator = translator;

            //declare the view we will be rendering
            RenderArgs args = new RenderArgs();
            args.ViewName = "0_HelloWorld";//this maps to file Views\0_HelloWorld.cshtml
            
            //create a writer responsible for writing text. In this case, we'll render to memory
            Stream memStream = new MemoryStream();
            IByteStream stream = new SystemByteStream(memStream);
            IContextWriter writer = new ContextWriter(stream);
            args.Writer = writer;

            //assign a data model for binding to the view. We don't have any special
            //model this time, so we'll just pass in this very form to demonstrate
            //the technique only
            args.Model = this;

            //ask the renderer to render the view
            ((IViewRenderer)renderer).Render(args);

            //read back the rendered view as text
            stream.Seek(0, SeekFrom.Begin);
            TextReader reader = new StreamReader(memStream);
            txtResult.Text = reader.ReadToEnd();
        }
        #endregion

        #region btnStart_Click
        private void btnStart_Click(object sender, EventArgs e)
        {
            StartServer();
        }
        #endregion

        #region btnStop_Click
        private void btnStop_Click(object sender, EventArgs e)
        {
            StopServer();
        }
        #endregion

        #endregion

        #region Server Events processing

        #region mServer_Started
        void mServer_Started(object sender, EventArgs e)
        {
            mIsStarting = false;
            UpdateUIBasedOnStatus();
        }
        #endregion

        #region mServer_StartFailed
        void mServer_StartFailed(object sender, Exception error)
        {
            mIsStarting = false;
            UpdateUIBasedOnStatus();

            this.RunOnUI((a) =>
            {
                Log.Warning("Could not start server");
                Log.Error(error);
            });
        }
        #endregion

        #region mServer_Stopped
        void mServer_Stopped(object sender, Exception error)
        {
            UpdateUIBasedOnStatus();
        }
        #endregion

        #endregion

        #region Update UI based on status
        bool mIsStarting = false;

        void UpdateUIBasedOnStatus()
        {
            this.RunOnUI((a) =>
            {
                if (mIsStarting)
                {
                    #region Server is starting
                    btnStart.Enabled = false;
                    btnStop.Enabled = false;
                    lblStatus.Text = "Starting...";
                    lblStatus.ForeColor = Color.Yellow;
                    #endregion
                }
                else if (mServer != null && mServer.IsListening)
                {
                    #region Server has started
                    btnStart.Enabled = false;
                    btnStop.Enabled = true;
                    lblStatus.Text = "Running...";
                    lblStatus.ForeColor = Color.GreenYellow;
                    #endregion
                }
                else
                {
                    #region Server has stopped
                    btnStart.Enabled = true;
                    btnStop.Enabled = false;
                    lblStatus.Text = "Stopped";
                    lblStatus.ForeColor = Color.Red;
                    #endregion
                }
            });
        }
        #endregion

        #region Intialize Server
        void InitializeServer()
        {
            if (mServer == null)
            {
                mServer = new WebServer();
                mServer.Root = mRootPath;
                mServer.Stopped += mServer_Stopped;
                mServer.StartFailed += mServer_StartFailed;
                mServer.Started += mServer_Started;

                //add mvc module to server
                var mvc = new MvcModule();
                mServer.Modules.Add(mvc);

                //hack
                mMvcModule = mvc;                
            }
            #region Defensive tracing
            else
            {
                //already initialized
            }
            #endregion
        }
        #endregion

        #region Start Server
        void StartServer()
        {
            InitializeServer();

            if (!mServer.IsListening)
            {
                mServer.Port = txtPort.Text.Parse<int>();
                mIsStarting = true;
                UpdateUIBasedOnStatus();
                mServer.Start();

                //register our sample controllers
                mMvcModule.ControllerManager.RegisterController(new HomeController());
                mMvcModule.ControllerManager.RegisterController(new SimpleController());
            }
            #region Defensive tracing
            else
            {
                //already started
            }
            #endregion
        }
        #endregion

        #region Stop Server
        void StopServer()
        {
            if (mServer != null && mServer.IsListening)
            {
                mServer.Stop();
            }
            #region Defensive tracing
            else
            {
                //not running, no need to stop
            }
            #endregion
        }
        #endregion

        #region On Load
        /// <summary>
        /// Initialize this form when form is loaded.
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            if (!DesignMode)
            {
#if DEBUG
                Log.Logger.SetPriorityFilter(LogPriority.Debug);
#endif
                UpdateUIBasedOnStatus();

#if DEBUG
                //mRootPath = Path.Combine(Application.StartupPath, "..\\..\\..\\..\\..\\Test site");
                mRootPath = @"Views\";
#else
                mRootPath = Path.Combine(Application.StartupPath, "Website");
#endif

                //make sure razor is available
                Services.Register(typeof(IViewRenderer), typeof(RazorViewRenderer));

                //auto-start
                StartServer();
#if DEBUG
                //btnShowTracer_Click(this, EventArgs.Empty);
#endif
            }
            #region Defensive tracing
            else
            {
                //don't do anything at design-time
            }
            #endregion

            //let my ancestor process its own logic
            base.OnLoad(e);
        }
        #endregion

        #region fmMain_FormClosing
        private void fmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopServer();
        }
        #endregion
        
        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public fmMain() 
        {
            InitializeComponent();
        }
        #endregion
    }
}
